home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 223 / emacssrc / emacs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-02-17  |  30.8 KB  |  1,319 lines

  1. /*
  2.  * This program is in public domain; written by Dave G. Conroy,
  3.  * substantially modified by Moshe Braner, July 1986.
  4.  * further additions by Dale Schumacher, December 1986.
  5.  * further additions by Dale Schumacher and John Stanley, Sept 1987.
  6.  *
  7.  * Parts of this program:
  8.  *    copyright (C) 1986 by Moshe Braner.
  9.  *    copyright (C) 1986,1987 by Dale Schumacher.
  10.  *    copyright (C) 1987 by John Stanley.
  11.  *
  12.  * Permission is granted to copy and use this program,
  13.  * provided that this copyright notice and the source
  14.  * code for the program are included in each copy,
  15.  * and that it is not sold for profit.
  16.  *
  17.  * This file contains the
  18.  * main driving routine, and some
  19.  * keyboard processing code, for the
  20.  * MicroEMACS screen editor.
  21.  */
  22.  
  23. #include    <stdio.h>
  24. #include    "ed.h"
  25.  
  26. #if    VMS
  27. #include    <ssdef.h>
  28. #define GOOD    (SS$_NORMAL)
  29. #endif
  30.  
  31. #if MSDOS
  32. #include    <fcntl.h>
  33. #endif
  34.  
  35. #ifndef GOOD
  36. #define GOOD    0
  37. #endif
  38.  
  39. #define BASE    0        /* mb: states of the machine */
  40. #define ESC    1
  41. #define ARG    2
  42. #define EXEC    3
  43.  
  44. /* NOTE: configurable variables defined the end of this file */
  45.  
  46. #if    AtST
  47. unsigned long _BLKSIZ = 32768;        /* dal: dLibs Malloc() granularity */
  48. #endif
  49.  
  50. char    vsn[] = VSN;            /* dal: version identification    */
  51. int    currow = 0;            /* Working cursor row        */
  52. int    curcol = 0;            /* Working cursor column    */
  53. int    thisflag = 0;            /* Flags, this command        */
  54. int    lastflag = 0;            /* Flags, last command        */
  55. int    curgoal = 0;            /* Goal column            */
  56. BUFFER  *curbp = NULL;            /* Current buffer        */
  57. BUFFER  *oldbp = NULL;            /* mb: previous buffer        */
  58. WINDOW  *curwp = NULL;            /* Current window        */
  59. BUFFER  *bheadp = NULL;            /* BUFFER listhead        */
  60. WINDOW  *wheadp = NULL;            /* WINDOW listhead        */
  61. BUFFER  *blistp = NULL;            /* Buffer list BUFFER        */
  62. BUFFER  *bhelpp = NULL;            /* Help screens BUFFER        */
  63. BUFFER    *bdirp = NULL;            /* dal: Directory BUFFER    */
  64. int    kbdm[NKBDM];            /* Macro            */
  65. int    *kbdmip = NULL;            /* Input  for above        */
  66. int    *kbdmop = NULL;            /* Output for above        */
  67. char    pat[NPAT];            /* Pattern            */
  68.  
  69. typedef struct  
  70.     {
  71.     int    k_code;            /* Key code            */
  72.     int    (*k_fp)();        /* Routine to handle it        */
  73.     }
  74.     KEYTAB;
  75.  
  76. extern  int    quit();            /* Quit                */
  77. extern  int    ctlxlp();        /* Begin macro            */
  78. extern  int    ctlxrp();        /* End macro            */
  79. extern  int    ctlxe();        /* Execute macro        */
  80. extern  int    fileread();        /* Get a file, read only    */
  81. extern  int    filevisit();        /* Get a file, read write    */
  82. extern  int    filewrite();        /* Write a file            */
  83. extern  int    filesave();        /* Save current file        */
  84. extern  int    filename();        /* Adjust file name        */
  85. extern  int    getccol();        /* Get current column        */
  86. extern  int    gotobol();        /* Move to start of line    */
  87. extern  int    forwchar();        /* Move forward by characters    */
  88. extern  int    gotoeol();        /* Move to end of line        */
  89. extern  int    backchar();        /* Move backward by characters  */
  90. extern  int    forwline();        /* Move forward by lines    */
  91. extern  int    backline();        /* Move backward by lines    */
  92. extern  int    forwpage();        /* Move forward by pages    */
  93. extern  int    backpage();        /* Move backward by pages    */
  94. extern  int    gotobob();        /* Move to start of buffer    */
  95. extern  int    gotoeob();        /* Move to end of buffer    */
  96. extern  int    setfillcol();        /* Set fill column.        */
  97. extern  int    setlmargin();        /* mb: added */
  98. extern  int    reformat();        /* mb: added */
  99. extern  int    setmark();        /* Set mark            */
  100. extern  int    swapmark();        /* Swap "." and mark        */
  101. extern  int    forwsearch();        /* Search forward        */
  102. extern  int    backsearch();        /* Search backwards        */
  103. extern  int    showcpos();        /* Show the cursor position    */
  104. extern  int    nextwind();        /* Move to the next window    */
  105. extern  int    prevwind();        /* Move to the previous window  */
  106. extern  int    onlywind();        /* Make current window only one */
  107. extern  int    splitwind();        /* Split current window        */
  108. extern  int    mvdnwind();        /* Move window down        */
  109. extern  int    mvupwind();        /* Move window up        */
  110. extern  int    enlargewind();        /* Enlarge display window.    */
  111. extern  int    listbuffers();        /* Display list of buffers    */
  112. extern  int    usebuffer();        /* Switch a window to a buffer  */
  113. extern    int    jumpbuffer();        /* dal: Jump to next buffer    */
  114. extern  int    killbuffer();        /* Make a buffer go away.    */
  115. extern  int    reposition();        /* Reposition window        */
  116. extern  int    refresh();        /* Refresh the screen        */
  117. extern  int    twiddle();        /* Twiddle characters        */
  118. extern  int    ltwiddle();        /* Twiddle lines - mb: added    */
  119. extern  int    tab();            /* Insert tab            */
  120. extern  int    newline();        /* Insert CR-LF            */
  121. extern  int    indent();        /* Insert CR-LF, then indent    */
  122. extern  int    indtog();        /* dal: toggle autoindent    */
  123. extern    int    ctrlm();        /* dal: newline()/indent()    */
  124. extern    int    ctrlj();        /* dal: indent()/newline()    */
  125. extern  int    openline();        /* Open up a blank line        */
  126. extern  int    deblank();        /* Delete blank lines        */
  127. extern  int    backword();        /* Backup by words        */
  128. extern  int    forwword();        /* Advance by words        */
  129. extern  int    forwdel();        /* Forward delete        */
  130. extern  int    backdel();        /* Backward delete        */
  131. extern  int    kill();            /* Kill forward            */
  132. extern  int    yank();            /* Yank back from killbuffer.    */
  133. extern  int    unyank();        /* mb: added            */
  134. extern  int    upperword();        /* Upper case word        */
  135. extern  int    lowerword();        /* Lower case word        */
  136. extern  int    upperregion();        /* Upper case region        */
  137. extern  int    lowerregion();        /* Lower case region        */
  138. extern  int    capword();        /* Initial capitalize word    */
  139. extern  int    delfword();        /* Delete forward word        */
  140. extern  int    delbword();        /* Delete backward word        */
  141. extern  int    killregion();        /* Kill region            */
  142. extern  int    copyregion();        /* Copy region to kill buffer    */
  143. extern  int    spawncli();        /* Run CLI in a subjob        */
  144. extern  int    spawn1();        /* Run a command in a subjob    */
  145. extern  int    quickexit();        /* low keystroke style exit    */
  146. extern  int    wrapword();        /* mb: added the rest, */
  147. extern  int    help();            /*   just in case      */
  148. extern  int    forw_brace();
  149. extern  int    back_brace();
  150. extern  int    instog();
  151. extern  int    editog();
  152. extern  int    visitog();
  153. extern  int    gotolinum();
  154. extern  int    forwparag();
  155. extern  int    backparag();
  156. extern  int    renambuf();
  157. extern  int    page_nextw();
  158. extern  int    back_nextw();
  159. extern  int    flush_kbuf();
  160. extern  int    emacs_quit();        /* fwd ref */
  161. extern    int    _stop();        /* fwd ref */
  162. extern  int    ctrlg();        /* fwd ref */
  163. extern  int    undo();            /* fwd ref */
  164. extern  int    bkill();        /* fwd ref */
  165. extern  int    defmacro();        /* fwd ref */
  166. #if    AtST
  167. extern    int    mousemode();        /* dal: fwd ref */
  168. extern    int    mfnleft();        /* dal: fwd ref */
  169. extern    int    mfnright();        /* dal: fwd ref */
  170. extern    int    dxmouse();        /* dal: added */
  171. extern    int    dymouse();        /* dal: added */
  172. #endif
  173. extern    int    save_cfg();        /* dal: fwd ref */
  174.  
  175. /*
  176.  * Command table.
  177.  * This table  is *roughly* in ASCII
  178.  * order, left to right across the characters
  179.  * of the command. This expains the funny
  180.  * location of the control-X commands.
  181.  */
  182. KEYTAB  keytab[] = 
  183.     {
  184.     CNTL|'@',        _stop,        /* dal: do nothing */
  185.     CNTL|'A',        gotobol,
  186.     CNTL|'B',        backchar,
  187.     CNTL|'C',        quit,        /* mb: was C-X C-C */
  188.      ED|CNTL|'D',        forwdel,
  189.     CNTL|'E',        gotoeol,
  190.     CNTL|'F',        forwchar,
  191.     CNTL|'G',        undo,
  192.      ED|CNTL|'H',        backdel,
  193.      ED|CNTL|0x3F,        forwdel,    /* mb: DELETE key */
  194. /*   ED|CNTL|0x3F,        backdel,    - if you want DEL=BS */
  195.      ED|CNTL|'I',        tab,
  196.      ED|CNTL|'J',        ctrlj,
  197.      ED|CNTL|'K',        kill,
  198.     CNTL|'L',        refresh,
  199.      ED|CNTL|'M',        ctrlm,
  200.     CNTL|'N',        forwline,
  201.      ED|CNTL|'O',        openline,
  202.     CNTL|'P',        backline,
  203. #if    V7
  204.     /* skip these */
  205. #else
  206.     CNTL|'S',        forwsearch,
  207. #endif
  208.     CNTL|'R',        backsearch,
  209.      ED|CNTL|'T',        twiddle,
  210.     CNTL|'V',        forwpage,
  211.      ED|CNTL|'W',        killregion,
  212.      ED|CNTL|'Y',        yank,
  213.     CNTL|'Z',        quickexit,    /* quick save and exit  */
  214.     CTLX|CNTL|'C',        spawncli,    /* Run CLI in subjob.    */
  215.     CTLX|CNTL|'E',        editog,        /* mb: added */
  216.     CTLX|CNTL|'F',        filename,
  217.     CTLX|CNTL|'B',        renambuf,    /* mb: added */
  218.     CTLX|CNTL|'R',        fileread,
  219. #if V7
  220.     /* skip */
  221. #else
  222.      ED|CTLX|CNTL|'S',        filesave,
  223. #endif
  224.     CTLX|CNTL|'I',        indtog,        /* dal: added */
  225.      ED|CTLX|CNTL|'T',        ltwiddle,    /* mb: added */
  226.     CTLX|CNTL|'V',        filevisit,
  227.      ED|CTLX|CNTL|'W',        filewrite,
  228.     CTLX|CNTL|'X',        swapmark,
  229.      ED|CTLX|CNTL|'Y',        unyank,        /* mb: added */
  230.     CTLX|CNTL|'Z',        emacs_quit,
  231.     CTLX|' ',        setmark,
  232.     CTLX|'?',        listbuffers,
  233.     CTLX|'!',        spawn1,
  234.     CTLX|'=',        showcpos,
  235.     CTLX|'(',        ctlxlp,
  236.     CTLX|')',        ctlxrp,
  237.     CTLX|'1',        onlywind,
  238.     CTLX|'2',        splitwind,
  239.     CTLX|'B',        usebuffer,
  240.     CTLX|'E',        ctlxe,
  241.      ED|CTLX|'F',        reformat,    /* mb: added */
  242.     CTLX|'I',        indtog,        /* dal: added */
  243.     CTLX|'J',        jumpbuffer,    /* dal: added */
  244.     CTLX|'K',        killbuffer,
  245.     CTLX|'L',        setlmargin,    /* mb: added */
  246.     CTLX|'M',        defmacro,    /* mb: added */
  247.     CTLX|'N',        nextwind,
  248.     CTLX|'O',        nextwind,    /* mb: EMACS-like */
  249.     CTLX|'P',        prevwind,
  250.     CTLX|'Q',        visitog,    /* mb: added */
  251.     CTLX|'R',        setfillcol,
  252.      ED|CTLX|'S',        filesave,    /* mb: instead of ^X^S  */
  253.     CTLX|'V',        page_nextw,    /* mb: added */
  254.     CTLX|'Y',        flush_kbuf,    /* dal: instead of META-Y */
  255.     CTLX|'Z',        back_nextw,    /* mb: added */
  256.     META|'!',        reposition,
  257. #if    VT100
  258.     /* skip this - it clashes with function key codes */
  259. #else
  260. #if    LK201
  261.     /* skip */
  262. #else
  263.     META|']',        forw_brace,    /* mb: added */
  264.     META|'[',        back_brace,    /* mb: added */
  265. #endif
  266. #endif
  267.     META|CNTL|'C',        save_cfg,    /* dal: added */
  268.     META|')',        forw_brace,    /* mb: added */
  269.     META|'}',        forw_brace,    /* mb: added */
  270.     META|'{',        back_brace,    /* mb: added */
  271.     META|'(',        back_brace,    /* mb: added */
  272.     META|'.',        setmark,
  273.     META|' ',        setmark,
  274.     META|'>',        gotoeob,
  275.     META|'<',        gotobob,
  276.     META|'B',        backword,
  277.     META|'F',        forwword,
  278.     META|'G',        gotolinum,    /* mb: added */
  279.     META|'I',        instog,        /* mb: added */
  280.     META|'R',        backsearch,
  281.     META|'S',        forwsearch,
  282.     META|'V',        backpage,
  283.     META|'W',        copyregion,
  284. #if    AtST
  285.     META|'M',        mousemode,    /* dal: added */
  286.     META|'X',        dxmouse,    /* dal: added */
  287.     META|'Y',        dymouse,    /* dal: added */
  288. #endif
  289.  
  290. #if    EXTRA
  291.  
  292.      ED|CTLX|CNTL|'L',        lowerregion,
  293.     CTLX|CNTL|'N',        mvdnwind,
  294.      ED|CTLX|CNTL|'O',        deblank,
  295.     CTLX|CNTL|'P',        mvupwind,
  296.      ED|CTLX|CNTL|'U',        upperregion,
  297.     CTLX|'^',        enlargewind,
  298.      ED|META|CNTL|'H',        delbword,
  299.      ED|META|'C',        capword,
  300.      ED|META|'D',        delfword,
  301.      ED|META|'L',        lowerword,
  302.     META|'N',        forwparag,    /* mb: added */
  303.     META|'P',        backparag,    /* mb: added */
  304.      ED|META|'U',        upperword,
  305.      ED|META|CNTL|0x3F,        delbword,
  306.  
  307. #endif    /* EXTRA */
  308.  
  309. /* JLS: 9/8/87 - Common keytable for MS-DOS and Atari ST */
  310. #if    AtST|MSDOS                    /* mb: added */
  311.  
  312.     FUNC|0x4B,        backchar,    /* <-- */
  313.     FUNC|SHFT|0x4B,        backword,
  314.     FUNC|META|0x4B,        gotobol,
  315.     FUNC|SHFT|0x73,        gotobol,
  316.     FUNC|0x4D,        forwchar,    /* --> */
  317.     FUNC|SHFT|0x4D,        forwword,
  318.     FUNC|META|0x4D,        gotoeol,
  319.     FUNC|SHFT|0x74,        gotoeol,
  320.     FUNC|0x50,        forwline,
  321.     FUNC|0x48,        backline,
  322. #if    EXTRA
  323.     FUNC|SHFT|0x50,        mvdnwind,
  324.     FUNC|ALT|SHFT|0x50,    forwpage,    /* dal: added, see ttgetc() */
  325.     FUNC|META|0x50,        forwparag,
  326.     FUNC|SHFT|0x48,        mvupwind,
  327.     FUNC|ALT|SHFT|0x48,    backpage,    /* dal: added, see ttgetc() */
  328.     FUNC|META|0x48,        backparag,
  329. #endif
  330.     FUNC|0x61,        undo,       /* Undo */
  331.     FUNC|SHFT|0x61,        flush_kbuf,
  332.      ED|FUNC|0x53,        forwdel,    /* Del */
  333.      ED|FUNC|SHFT|0x53,        kill,
  334.      ED|FUNC|0x0E,        backdel,    /* Backspace */
  335.      ED|FUNC|SHFT|0x0E,        bkill,
  336. #if    EXTRA
  337.      ED|FUNC|META|0x53,        delfword,    /* Delete */
  338.      ED|FUNC|META|0x0E,        delbword,    /* Backspace */
  339. #endif
  340. #if    MSDOS
  341.     FUNC|'I',        backpage,    /* Pg Up */
  342.     FUNC|'Q',        forwpage,    /* Pg Dn */
  343.     FUNC|'O',        jumpbuffer,    /* End */
  344. #endif
  345.     FUNC|'G',        reposition,    /* Clr/Home  */
  346.     FUNC|META|'G',        gotobob,    /* Esc-Home  */
  347.     FUNC|SHFT|0x77,        gotoeob,    /* Ctrl-Home */
  348.      ED|FUNC|'R',        openline,    /* Insert */
  349. #if    AtST
  350.     FUNC|ALT|0x74,        mfnleft,    /* dal: Left mouse button */
  351.     FUNC|ALT|0x75,        mfnright,    /* dal: Right mouse button */
  352. #endif
  353. #if EXTRA
  354.      ED|FUNC|SHFT|0x52,        deblank,
  355. #endif
  356.     FUNC|0x3B,        ctlxe,        /* F1  */
  357.     FUNC|SHFT|0x3B,        defmacro,
  358.     FUNC|0x3C,        setmark,    /* F2  */
  359.     FUNC|SHFT|0x3C,        swapmark,
  360.     FUNC|0x3D,        usebuffer,    /* F3  */
  361.     FUNC|SHFT|0x3D,        filevisit,
  362.      ED|FUNC|0x3E,        fileread,    /* F4  */
  363.     FUNC|SHFT|0x3E,        filewrite,
  364.      ED|FUNC|0x3F,        kill,        /* F5  */
  365.      ED|FUNC|SHFT|0x3F,        killregion,
  366.      ED|FUNC|0x40,        yank,        /* F6  */
  367.     FUNC|SHFT|0x40,        copyregion,
  368.     FUNC|0x41,        backsearch,    /* F7  */
  369.     FUNC|SHFT|0x41,        back_brace,
  370.     FUNC|0x42,        forwsearch,    /* F8  */
  371.     FUNC|SHFT|0x42,        forw_brace,
  372.     FUNC|0x43,        backpage,    /* F9  */
  373.     FUNC|SHFT|0x43,        back_nextw,
  374.     FUNC|0x44,        forwpage,    /* F10 */
  375.     FUNC|SHFT|0x44,        page_nextw,
  376. #if    HELP
  377.     FUNC|0x62,        help,        /* Help */
  378. #else
  379.     FUNC|0x62,        listbuffers,
  380. #endif
  381.     FUNC|SHFT|0x62,        listbuffers,
  382.     /* Alt to act as Ctrl-X-Ctrl: */
  383.     FUNC|SHFT|0x2E,        spawncli,    /* Alt-C */
  384.     FUNC|SHFT|0x20,        spawn1,        /* Alt-D */
  385.     FUNC|SHFT|0x12,        editog,        /* Alt-E */
  386.      ED|FUNC|SHFT|0x14,        ltwiddle,    /* Alt-T */
  387.     FUNC|SHFT|0x2D,        swapmark,    /* Alt-X */
  388.     /* Alt to act as Ctrl-X: */
  389.     FUNC|SHFT|0x83,        showcpos,
  390.     FUNC|SHFT|0x78,        onlywind,
  391.     FUNC|SHFT|0x79,        splitwind,
  392.     FUNC|SHFT|0x30,        usebuffer,
  393.     FUNC|SHFT|0x24,        jumpbuffer,    /* dal: Alt-J */
  394.      ED|FUNC|SHFT|0x21,        reformat,
  395.     FUNC|SHFT|0x25,        killbuffer,
  396.     FUNC|SHFT|0x26,        setlmargin,
  397.     FUNC|SHFT|0x32,        defmacro,
  398.     FUNC|SHFT|0x31,        nextwind,
  399.     FUNC|SHFT|0x19,        prevwind,
  400.     FUNC|SHFT|0x13,        setfillcol,
  401.     FUNC|SHFT|0x10,        visitog,
  402.      ED|FUNC|SHFT|0x1F,        filesave,
  403.     FUNC|SHFT|0x2F,        filevisit,
  404.     /* Other Alt- functions: */
  405.     FUNC|SHFT|0x22,        gotolinum,    /* Alt-G */
  406.     FUNC|SHFT|0x17,        instog,        /* Alt-I */
  407.      ED|FUNC|SHFT|0x11,        filewrite,    /* Alt-W */
  408.      ED|FUNC|SHFT|0x18,        openline,    /* Alt-O */
  409.     FUNC|SHFT|0x80,        back_brace,    /* Alt-( */
  410.     FUNC|SHFT|0x81,        forw_brace,    /* Alt-) */
  411. #if    EXTRA
  412.     FUNC|SHFT|0x7D,        enlargewind,    /* Alt-^ */
  413. #endif
  414.     /* Still available:
  415.     FUNC|SHFT|0x23,        Alt-H
  416.     FUNC|SHFT|0x16,        Alt-U
  417.         FUNC|SHFT|0x15,        Alt-Y
  418.     FUNC|SHFT|0x2C,        Alt-Z
  419.     FUNC|SHFT|0x7A,        Alt-3
  420.     FUNC|SHFT|0x7B,        Alt-4
  421.     FUNC|SHFT|0x7C,        Alt-5
  422.     FUNC|SHFT|0x7E,        Alt-7
  423.     FUNC|SHFT|0x7F,        Alt-8
  424.     FUNC|SHFT|0x82,        Alt '-'
  425.      */
  426. #endif    /* AtST */
  427.  
  428. #if    HELP                    /* mb: added */
  429.     META|'?',        help,
  430.     META|CNTL|'[',        help,
  431. #ifdef    HELPCH
  432.     HELPCH,            help,
  433. #endif
  434. #endif    /* HELP */
  435.  
  436.     0,            _stop
  437.     };
  438.  
  439. #define NKEYTAB (sizeof(keytab)/sizeof(keytab[0]))
  440.  
  441. main(argc, argv)        /* mb: completely rewritten */
  442.     int argc;
  443.     register char *argv[];
  444.     {
  445.     register int    c;
  446.     register int    f = FALSE;
  447.     register int    n = 1;
  448.     register int    state;
  449.     register char    *p;
  450.     register BUFFER *bp;
  451.     char    bname[NBUFN];
  452.     char    fname[NFILEN];
  453.     int    negarg;
  454.     int    view_only = FALSE;
  455.     int    wild = FALSE;
  456.     BUFFER    *b1 = NULL;
  457.     char    *wildcard();
  458.  
  459.     vtinit();                /* dal: do Displays 1st    */
  460.     kbdm[0] = CTLX | ')';            /* Empty macro        */
  461.     while(wild || --argc)
  462.         {
  463.         if(wild)
  464.             {
  465.             if(p = wildcard(NULL))
  466.                 p = strcpy(fname, p);
  467.             else
  468.                 {
  469.                 wild = FALSE;
  470.                 continue;
  471.                 }
  472.             }
  473.         else
  474.             {
  475.             p = *++argv;
  476.             if(strchr(p, '*') || strchr(p, '?'))
  477.                 {
  478.                 if(p = wildcard(p))
  479.                     {
  480.                     wild = TRUE;
  481.                     p = strcpy(fname, p);
  482.                     }
  483.                 else
  484.                     continue;
  485.                 }
  486.             }
  487.         if(*p == '-')             /* command line switch */
  488.             {
  489.             p += 2;
  490.             switch(tolower(*(p-1))) 
  491.                 {
  492.                 case 'v':
  493.                     view_only = TRUE;
  494.                     break;
  495.                 case 'g':
  496.                     if(b1)
  497.                         gotolinum(TRUE, atoi(p));
  498.                     break;
  499.                 }
  500.             }
  501. /*----------------------------------------------------------------------*/
  502.         else if (b1 == NULL) 
  503.             {
  504.             makename(bname, p);    /* initial buffer name    */
  505.             edinit(bname);        /* init buffers, etc.    */
  506.             update();        /* draw screen first    */
  507.             if(readin(p)==FIOFNF)     /* file not found */
  508.                 {
  509.                 if(view_only)
  510.                     mlwrite("[%s not found]", p);
  511.                 else 
  512.                     {
  513.                     mlwrite("[New file]");
  514.                     fullpath(curbp->b_fname, p);
  515.                     }
  516.                 }
  517.             else
  518.                 fullpath(curbp->b_fname, p);
  519.             if(view_only)
  520.                 curbp->b_flag &= ~BFEDIT;
  521.             b1 = curbp;
  522.             }
  523.         else 
  524.             {
  525.             makename(bname, p);    /* derive buffer name    */
  526.             if((bp = bfind(bname, TRUE, BFEDIT)) == NULL)
  527.                 continue;
  528.             gotobuf(bp);
  529.             if(readin(p) != FIOEOF) 
  530.                 {
  531.                 gotobuf(oldbp);        /* switch back */
  532.                 freebuf(oldbp);        /* now oldbp == bad */
  533.                 continue;
  534.                 }
  535.             fullpath(bp->b_fname, p);    /* dal: normalize */
  536.             bp->b_flag &= ~(BFTEMP|BFCHG);
  537.             if(view_only)
  538.                 bp->b_flag &= ~BFEDIT;
  539.             }
  540. /*----------------------------------------------------------------------*/
  541.         }
  542.     if(b1 == NULL)             /* no initial file */
  543.         {
  544.         strcpy(bname, "main");
  545.         edinit(bname);            /* init buffers, etc.    */
  546.         mlpending("Hit [%s] for help. [%s] reads a file.",
  547.             (AtST ? "HELP" : "ESC-?"),
  548.             (AtST|MSDOS ? "F4" : "^X^R"));
  549.         }
  550.     else
  551.         gotobuf(b1);
  552.  
  553.     update();                /* draw screen        */
  554.     lastflag = 0;                /* Fake last flags.    */
  555.     negarg = FALSE;
  556.     f = FALSE;
  557.     n = 1;
  558.     update();
  559.     c = getkey();
  560.     mlerase();
  561.     state = BASE;
  562.  
  563.     for(;;)                 /* main loop */
  564.         {
  565.     switch (state) 
  566.         {
  567.  
  568.     case BASE:
  569.         if (c==(CNTL|'U')) 
  570.             {
  571.             n = 4;
  572.             mlwrite("arg: 4");
  573.             c = getkey();
  574.             state = ARG;
  575.             break;
  576.             }
  577.         if (c == METACH) 
  578.             {
  579.             c = getkey();
  580.             state = ESC;
  581.             break;
  582.             }
  583.         if (c == (CNTL|'X')) 
  584.             {
  585.             c = getkey();
  586.             if (c == (CNTL|'G')
  587. #if AtST
  588.              || c == (FUNC|0x61)
  589. #endif
  590.                     )     /* Undo */
  591.                 {
  592.                 c = getkey();
  593.                 break;
  594.                 }
  595.             if (c>='a' && c<='z')
  596.                 c -= 0x20;    /* force upper case */
  597.             c |= CTLX;
  598.             }
  599.         state = EXEC;
  600.         break;
  601.  
  602.     case ESC:
  603.         if (c=='-' || (c>='0' && c<='9')) 
  604.             {
  605.             state = ARG;
  606.             break;
  607.             }
  608. #if  VT100
  609.         if (c=='[' || c=='O') 
  610.             {
  611.             state = EXEC;
  612.             c = escseq(c);
  613.             if (! c) 
  614.                 {
  615.                 c = getkey();
  616.                 state = BASE;
  617.                 }
  618.             break;
  619.             }
  620. #endif
  621. #if  LK201
  622.         if (c=='[' || c=='O') 
  623.             {
  624.             state = EXEC;
  625.             c = escseq(c);
  626.             if (! c) 
  627.                 {
  628.                 c = getkey();
  629.                 state = BASE;
  630.                 }
  631.             break;
  632.             }
  633. #endif
  634.         if (c == (CNTL|'G')
  635. #if AtST
  636.          || c == (FUNC|0x61)
  637. #endif
  638.                     )     /* Undo */
  639.             {
  640.             c = getkey();
  641.             state = BASE;
  642.             break;
  643.             }
  644.         if (c>='a' && c<='z')
  645.             c -= 0x20;        /* force upper case */
  646.         c |= META;
  647.         state = EXEC;
  648.         break;
  649.  
  650.     case ARG:
  651.         if (c == (CNTL|'U')) 
  652.             {
  653.             n *= 4;
  654.             }
  655.         else if (c=='-' && f==FALSE) 
  656.             {
  657.             negarg = TRUE;
  658.             n = (-1);
  659.             }
  660.         else if  (c==(CNTL|'H')  || c==(CNTL|0x3F)
  661. #if AtST
  662.              || c==(FUNC|0x0E) || c==(FUNC|0x53)
  663. #endif
  664.                             ) 
  665.             {
  666.             n /= 10;
  667.             if (n == 0)
  668.                 negarg = FALSE;
  669.             }
  670.         else if (c == (FUNC|0x61)
  671. #if AtST
  672.             || c == (CNTL|'G')
  673. #endif
  674.                     )  /* Undo */
  675.             {
  676.             f = FALSE;
  677.             n = 1;
  678.             mlwrite("[aborted]");
  679.             update();        /* put cursor back */
  680.             c = getkey();
  681.             state = BASE;
  682.             break;
  683.             }
  684.         else if (c>='0' && c<='9') 
  685.             {
  686.             if (f == FALSE) 
  687.                 {
  688.                 n = 0;
  689.                 f = TRUE;
  690.                 }
  691.             n = 10*n + ((negarg) ? ('0'-c) : (c-'0'));
  692.             }
  693.         else 
  694.             {
  695.             state = BASE;
  696.             f = TRUE;
  697.             break;
  698.             }
  699.         mlwrite("arg: %d",n);
  700.         c = getkey();
  701.         break;
  702.  
  703.     case EXEC:
  704.         if (c == (CNTL|'Q') || c == (META|'Q')) 
  705.             {
  706.             c = (*term.t_getchar)();
  707.             c &= 0xFF;
  708.             }
  709. #if AtST
  710.         if (c == (FUNC|SHFT|0x1E))         /* Alt-A */
  711.             {
  712.             c = (*term.t_getchar)();
  713.             c &= 0xFF;
  714.             c |= 0x80;    /* set MSB: alternate char set */
  715.             }
  716. #endif
  717.         if (kbdmip != NULL)         /* Save macro strokes.  */
  718.             {
  719.             if (c!=(CTLX|')') && kbdmip>&kbdm[NKBDM-6]) 
  720.                 {
  721.                 ctrlg(FALSE, 0);
  722.                 c = getkey();
  723.                 state = BASE;
  724.                 break;
  725.                 }
  726.             if (f != FALSE) 
  727.                 {
  728.                 *kbdmip++ = (CNTL|'U');
  729.                 *kbdmip++ = n;
  730.                 }
  731.             *kbdmip++ = c;
  732.             }
  733.         execute(c, f, n);        /* Do it, finally */
  734.         f = FALSE;
  735.         n = 1;
  736.         negarg = FALSE;
  737.         update();            /* Fix up the screen    */
  738.         c = getkey();
  739.         if (mpresf != FALSE) 
  740.             {
  741.             mlerase();
  742.             }
  743.         state = BASE;
  744.         break;
  745.  
  746.     default:
  747.         exit(0);            /* bug if you're here */
  748.         }                /* end of switch */
  749.         }                /* end of for()  */
  750.     }                    /* end of main() */
  751.  
  752. /*
  753.  * Initialize all of the buffers
  754.  * and windows. The buffer name is passed down as
  755.  * an argument, because the main routine may have been
  756.  * told to read in a file by default, and we want the
  757.  * buffer name to be right.
  758.  */
  759. edinit(bname)
  760. char    bname[];
  761.     {
  762.     register BUFFER *bp;
  763.     register WINDOW *wp;
  764.  
  765.     bp = bfind(bname, TRUE, BFEDIT);    /* First buffer        */
  766.     blistp = bfind("[List]", TRUE, BFTEMP); /* Buffer list buffer    */
  767.     bhelpp = bfind("[Help]", TRUE, BFTEMP); /* Help screens buffer    */
  768.     bdirp = bfind("[Dir]", TRUE, BFTEMP);   /* dal: Directory buffer*/
  769.     wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window        */
  770.     if(bp==NULL || wp==NULL || blistp==NULL || bhelpp==NULL || bdirp==NULL)
  771.         exit(1);
  772.     curbp  = bp;                /* Make this current    */
  773.     wheadp = wp;
  774.     curwp  = wp;
  775.     wp->w_wndp  = NULL;            /* Initialize window    */
  776.     wp->w_bufp  = bp;
  777.     bp->b_nwnd  = 1;            /* Displayed.        */
  778.     wp->w_linep = bp->b_linep;
  779.     wp->w_dotp  = bp->b_linep;
  780.     wp->w_doto  = 0;
  781.     wp->w_markp = NULL;
  782.     wp->w_marko = 0;
  783.     wp->w_toprow = 0;
  784.     wp->w_ntrows = term.t_nrow-1;        /* "-1" for mode line.  */
  785.     wp->w_force = 0;
  786.     wp->w_flag  = WFMODE|WFHARD;        /* Full.        */
  787.     }
  788.  
  789. #if  VT100
  790. int escseq(c)
  791.     register int c;
  792.     {
  793.     if (c == '[')             /* Arrows and extras.    */
  794.         {
  795.         c = (*term.t_getchar)();
  796.         if (c == 'A')
  797.             return (CNTL | 'P');
  798.         if (c == 'B')
  799.             return (CNTL | 'N');
  800.         if (c == 'C')
  801.             return (CNTL | 'F');
  802.         if (c == 'D')
  803.             return (CNTL | 'B');
  804.         return (0);
  805.         }
  806.     if (c == 'O') 
  807.         {
  808.         c = (*term.t_getchar)();
  809.         if (c == 'P')    /* PF1 */
  810.             return (META | 'B');
  811.         if (c == 'Q')    /* PF2 */
  812.             return (META | 'F');
  813.         if (c == 'R')    /* PF3 */
  814.             return (META | '.');
  815.         if (c == 'S')    /* PF4 */
  816.             return (CTLX | 'E');
  817.         return (0);
  818.         }
  819.     }
  820. #endif
  821.  
  822. #if  LK201
  823. int escseq(c)
  824.     register int c;
  825.     {
  826.     if (c == '[')             /* Arrows and extras.    */
  827.         {
  828.         c = (*term.t_getchar)();
  829.         if (c == 'A')
  830.             return (CNTL | 'P');
  831.         if (c == 'B')
  832.             return (CNTL | 'N');
  833.         if (c == 'C')
  834.             return (CNTL | 'F');
  835.         if (c == 'D')
  836.             return (CNTL | 'B');
  837.         if (c>='0' && c<='9') 
  838.             {
  839.             i = 0;
  840.             do 
  841.                 {
  842.                 i = 10*i + c - '0';
  843.                 c = (*term.t_getchar)();
  844.                 }
  845.                 while (c>='0' && c<='9');
  846.             if (c=='~' && i<35 && (c=lkmap[i]))
  847.                 return (c);
  848.             }
  849.         return (0);
  850.         }
  851.     if (c == 'O') 
  852.         {
  853.         c = (*term.t_getchar)();
  854.         if (c == 'P')    /* PF1 */
  855.             return (META | 'B');
  856.         if (c == 'Q')    /* PF2 */
  857.             return (META | 'F');
  858.         if (c == 'R')    /* PF3 */
  859.             return (META | '.');
  860.         if (c == 'S')    /* PF4 */
  861.             return (CTLX | 'E');
  862.         return (0);
  863.         }
  864.     }
  865. #endif
  866.  
  867. /*
  868.  * This is the general command execution
  869.  * routine. It handles the fake binding of all the
  870.  * keys to "self-insert". It also clears out the "thisflag"
  871.  * word, and arranges to move it to the "lastflag", so that
  872.  * the next command can look at it. Return the status of
  873.  * command.
  874.  * mb: added the BFEDIT / ED stuff.
  875.  */
  876. execute(c, f, n)
  877.     register int    c;
  878.     {
  879.     register KEYTAB *ktp;
  880.     register int    k;
  881.     register int    d;
  882.     register int    status;
  883.  
  884.     if ((c & 0xFF00) == 0)
  885.         goto ascii;
  886.     d = c;
  887.     if (curbp->b_flag & BFEDIT)
  888.         d |= ED;
  889.     ktp = &keytab[0];            /* Look in key table.    */
  890.     while (ktp < &keytab[NKEYTAB]) 
  891.         {
  892.         k = ktp->k_code;
  893.         if (k==c || k==d)         /* mb: fit, ED| or not */
  894.             {
  895.             thisflag = 0;
  896.             status   = (*ktp->k_fp)(f, n);
  897.             lastflag = thisflag;
  898.             return (status);
  899.             }
  900.         ++ktp;
  901.         }
  902.     if (c != d) 
  903.         {
  904. #if GDEBUG
  905.         mlwrite("No such command (code 0x%x)", c);
  906. #else
  907.         mlwrite("No such command");
  908. #endif
  909.         return (FALSE);
  910.         }
  911.     /* else fall thru to "view-only" message */
  912. ascii:
  913.     if (! (curbp->b_flag & BFEDIT)) 
  914.         {
  915. #if AtST
  916.         mlwrite("View-only mode - Alt-E to edit");
  917. #else
  918.         mlwrite("View-only mode - ^X^E to edit");
  919. #endif
  920.         lastflag = 0;
  921.         return(FALSE);
  922.         }
  923.  
  924. #ifdef NEVER    /* moved and changed to act on ANY character... */
  925.     /*
  926.      * If a space was typed, fill column is defined, the argument is non-
  927.      * negative, and we are now past fill column, perform word wrap.
  928.      */
  929.     if (c==' ' && fillcol>0 && n>=0 && getccol(FALSE)>fillcol)
  930.         wrapword();
  931. #endif
  932.                     /* mb: skipped the ASCII check    */
  933.     if (n <= 0)                 /* Fenceposts.        */
  934.         {
  935.         lastflag = 0;
  936.         return (n<0 ? FALSE : TRUE);
  937.         }
  938.     thisflag = 0;                /* For the future.    */
  939.     status   = linsert(n, c, ovrstrk);    /* mb: added param    */
  940.     lastflag = thisflag;
  941.     if (fillcol>0 && n>=0 && getccol(FALSE)>fillcol)
  942.         wrapword();
  943.     return (status);
  944.     lastflag = 0;                /* Fake last flags.    */
  945.     return (FALSE);
  946.     }
  947.  
  948. indtog()
  949. /*
  950.  * Toggle auto-indent mode.  In auto-indent mode, ^M and ^J swap functions.
  951.  */
  952.     {
  953.     mlwrite("[auto-indent %s]", (autoindent = !autoindent) ? "on" : "off");
  954.     }
  955.  
  956. /*
  957.  * Read in a key. - mb: very much simplified.
  958.  * Convert ctrl keys to the internal character set.
  959.  */
  960. getkey() 
  961.     {
  962.     register int    c;
  963.     register int    t;
  964.  
  965.     c = (*term.t_getchar)();
  966. #ifdef CNTLCH
  967.     if (c == CNTLCH)             /* Apply C- prefix    */
  968.         {
  969.         c = (*term.t_getchar)();
  970.         c = toupper(c);            /* Force to upper    */
  971.         c |= CNTL;
  972.         }
  973. #endif
  974.     /* control -> CNTL */
  975.     t = c & 0x7F;
  976.     if ((!(FUNC & c)) && ((t < 0x20) || (t == 0x7F)))
  977.         c = CNTL | (c ^ 0x40);
  978.     return (c);
  979.     }
  980.  
  981. /*
  982.  * Fancy quit command, as implemented
  983.  * by Norm. If the current buffer has changed
  984.  * do a write current buffer and exit emacs,
  985.  * otherwise simply exit.
  986.  */
  987. quickexit(f, n)
  988.     {
  989.     if ((curbp->b_flag & BFCHG) != 0    /* Changed.        */
  990.     && (curbp->b_flag & BFTEMP) == 0)    /* Real.        */
  991.         filesave(f, n);
  992.     quit(f, n);                /* conditionally quit    */
  993.     }
  994.  
  995. /*
  996.  * Quit command. If an argument, always
  997.  * quit. Otherwise confirm if a buffer has been
  998.  * changed and not written out. Normally bound
  999.  * to "C-X C-C".
  1000.  */
  1001. quit(f, n)
  1002.     {
  1003.     register int    s;
  1004.  
  1005.     if (f != FALSE                /* Argument forces it.  */
  1006.     || anycb() == FALSE            /* All buffers clean.    */
  1007.     || (s=mlyesno("Discard changes")) == TRUE)    /* User says OK. */
  1008.         {
  1009.         vttidy();
  1010.         exit(GOOD);
  1011.         }
  1012.     mlwrite("[aborted]");    
  1013.     return (s);
  1014.     }
  1015.  
  1016. /* mb: added */
  1017. emacs_quit(f, n) 
  1018.     {
  1019.     if (f)
  1020.         return(quickexit(FALSE, 1));
  1021.     else
  1022.         return(quit(f, n));
  1023.     }
  1024.  
  1025. /*
  1026.  * Begin a keyboard macro.
  1027.  * Error if not at the top level
  1028.  * in keyboard processing. Set up
  1029.  * variables and return.
  1030.  */
  1031. ctlxlp(f, n)
  1032.  
  1033.     {
  1034.     if (kbdmip!=NULL || kbdmop!=NULL) 
  1035.         {
  1036.         mlwrite("Not now");
  1037.         return (FALSE);
  1038.         }
  1039.     mlwrite("[Start macro]");
  1040.     kbdmip = &kbdm[0];
  1041.     return (TRUE);
  1042.     }
  1043.  
  1044. /*
  1045.  * End keyboard macro. Check for
  1046.  * the same limit conditions as the
  1047.  * above routine. Set up the variables
  1048.  * and return to the caller.
  1049.  */
  1050. ctlxrp(f, n)
  1051.     {
  1052.     if (kbdmip == NULL) 
  1053.         {
  1054.         mlwrite("Not now");
  1055.         return (FALSE);
  1056.         }
  1057.     *(--kbdmip) = CTLX|')';        /* in case CTLX|'M' */
  1058.     mlwrite("[End macro]");
  1059.     kbdmip = NULL;
  1060.     return (TRUE);
  1061.     }
  1062.  
  1063. /* mb: added.
  1064.  */
  1065. defmacro(f, n)
  1066.     {
  1067.     if (kbdmip == NULL)
  1068.         return (ctlxlp(f, n));
  1069.     else
  1070.         return (ctlxrp(f, n));
  1071.     }
  1072.  
  1073. /*
  1074.  * Execute a macro.
  1075.  * The command argument is the
  1076.  * number of times to loop. Quit as
  1077.  * soon as a command gets an error.
  1078.  * Return TRUE if all ok, else
  1079.  * FALSE.
  1080.  */
  1081. ctlxe(f, n)
  1082.     {
  1083.     register int    c;
  1084.     register int    af;
  1085.     register int    an;
  1086.     register int    s;
  1087.  
  1088.     if (kbdmip!=NULL || kbdmop!=NULL) 
  1089.         {
  1090.         mlwrite("Not now");
  1091.         return (FALSE);
  1092.         }
  1093.     if (n <= 0) 
  1094.         return (TRUE);
  1095.     do 
  1096.         {
  1097.         kbdmop = &kbdm[0];
  1098.         do 
  1099.             {
  1100.             af = FALSE;
  1101.             an = 1;
  1102.             if ((c = *kbdmop++) == (CNTL|'U')) 
  1103.                 {
  1104.                 af = TRUE;
  1105.                 an = *kbdmop++;
  1106.                 c  = *kbdmop++;
  1107.                 }
  1108.             s = TRUE;
  1109.             }
  1110.             while (c!=(CTLX|')') && (s=execute(c, af, an))==TRUE);
  1111.         kbdmop = NULL;
  1112.         }
  1113.         while (s==TRUE && --n);
  1114.     return (s);
  1115.     }
  1116.  
  1117. /*
  1118.  * Abort.
  1119.  * Beep the beeper.
  1120.  * Kill off any keyboard macro,
  1121.  * etc., that is in progress.
  1122.  * Sometimes called as a routine,
  1123.  * to do general aborting of
  1124.  * stuff.
  1125.  */
  1126. _stop(f, n)
  1127.     {
  1128.     if (kbdmip != NULL) 
  1129.         {
  1130.         kbdm[0] = (CTLX|')');
  1131.         kbdmip  = NULL;
  1132.         }
  1133.     return (ABORT);
  1134.     }
  1135.  
  1136. ctrlg(f, n)
  1137.     {
  1138.     mlwrite("[aborted]");        /* mb: instead of beep */
  1139.     return( _stop());
  1140.     }
  1141.  
  1142. /* mb: added.
  1143.  */
  1144. undo(f, n)
  1145.     {
  1146.     if ((lastflag&CFKILL))        /* If last command was Kill */
  1147.         return (yank(0, 1));
  1148.     if ((lastflag&CFYANK))        /* If last command was Yank */
  1149.         return (unyank(0, 1));
  1150.     if ((lastflag&CFSPLIT))        /* After help or buflist */
  1151.         return (onlywind(0, 1));
  1152.     if (kbdmip != NULL)        /* Inside macro definition */
  1153.         return (ctrlg(f,n));
  1154.     else
  1155.         return (ABORT);
  1156.     }
  1157.  
  1158. #if    AtST
  1159. /*
  1160.  * dal: added support for Atari mouse.
  1161.  */
  1162. static    int    mfncut = FALSE;
  1163.  
  1164. mousemode(f, n)            /* switch between bound and cut/paste action */
  1165.     {
  1166.     mousef = !mousef;
  1167.     mlwrite("Mouse buttons now do %s functions",
  1168.         (mousef ? "bound" : "mark/cut/paste"));
  1169.     return(TRUE);
  1170.     }
  1171.  
  1172. mfnleft(f, n)            /* MARK mouse function */
  1173.     {
  1174.     mfncut = TRUE;
  1175.     return(setmark(f, n));
  1176.     }
  1177.  
  1178. mfnright(f, n)            /* CUT/PASTE mouse function */
  1179.     {
  1180.     if (mfncut) 
  1181.         {
  1182.         mfncut = FALSE;
  1183.         if (curbp->b_flag & BFEDIT)
  1184.             return(killregion(f, n));
  1185.         else
  1186.             return(copyregion(f, n));
  1187.         }
  1188.     else 
  1189.         {
  1190.         if (curbp->b_flag & BFEDIT)
  1191.             return(yank(f, n));
  1192.         else 
  1193.             {
  1194.             mlwrite("View-only mode - Alt-E to edit");
  1195.             return(FALSE);
  1196.             }
  1197.         }
  1198.     }
  1199. #endif    /* AtST */
  1200.  
  1201. /*
  1202.  *    The following is code to handle the "clone" operation for saving
  1203.  *    new default settings in an EMACS executable file.
  1204.  */
  1205. #if    AtST
  1206. static char        NAMEN[] = "EMACS.TTP";
  1207. #define    MODE_RWB    (O_RDWR)
  1208. #endif
  1209. #if    MSDOS
  1210. static char        NAMEN[] = "EMACS.EXE";
  1211. #define    MODE_RWB    (O_RDWR|O_BINARY)
  1212. #endif
  1213.  
  1214. save_cfg()
  1215.     {
  1216.     register int c, n, h, i;
  1217.     register unsigned int bufsize;
  1218.     register char *buf, *p;
  1219.     register long ofst = (long)CFG_MSIZE;
  1220.  
  1221. #if    AtST
  1222.     unsigned long    memavail();
  1223.     unsigned long    space;
  1224. #else
  1225.     unsigned int    _memavl();
  1226. #endif
  1227.     char *malloc();
  1228.  
  1229.     if(mlyesno("Clone MicroEMACS") != TRUE)
  1230.         return(FALSE);
  1231.  
  1232.     if((h = open(NAMEN, MODE_RWB)) < 0) 
  1233.         {
  1234.         mlwrite("[Can't open %s]", NAMEN);
  1235.         return(FALSE);
  1236.         }
  1237.  
  1238. #if    AtST
  1239.     if ((space = memavail()) > 32000)
  1240.         space = 32000;
  1241.     if ((bufsize = (int)space) < 1024)
  1242. #else
  1243.     if ((bufsize = _memavl()) < 1024)
  1244. #endif
  1245.         {
  1246.         close(h);
  1247.         mlwrite("[Not enough memory to clone]");
  1248.         return(FALSE);
  1249.         }
  1250.  
  1251. #if    !AtST
  1252.     if (bufsize > 32000)
  1253.         bufsize = 32000;
  1254. #endif
  1255.     buf = malloc(bufsize);
  1256.  
  1257.     c = cfg.magic[0];
  1258.  
  1259.     n = read(h, (p = buf), bufsize);
  1260.     while (n >= sizeof(cfg)) 
  1261.         {
  1262.         if ((c == *p) && !strcmp(p+1, cfg.magic+1)) 
  1263.             {
  1264.             lseek(h, ofst, SEEK_SET);
  1265.             i = cfgchng;
  1266.             cfgchng = TRUE;
  1267.             n = write(h, &cfg.value[0], CFG_VSIZE);
  1268.             close(h);
  1269.             free(buf);
  1270.             if (n != CFG_VSIZE) 
  1271.                 {
  1272.                 cfgchng = i;
  1273.                 mlwrite("[Write error during clone]");
  1274.                 return(FALSE);
  1275.                 }
  1276.             mlwrite("[Clone successful]");
  1277.             return(TRUE);
  1278.             }
  1279.         --n;
  1280.         ++p;
  1281.         ++ofst;
  1282.         if (n < sizeof(cfg)) 
  1283.             {
  1284.             memcpy(buf, p, (i = n));
  1285.             if ((n = read(h, buf+n, bufsize-n)) < 0)
  1286.                 break;
  1287.             p = buf;
  1288.             n += i;
  1289.             }
  1290.         }
  1291.  
  1292.     mlwrite((n < 0)
  1293.         ? "[Read error during clone]"
  1294.         : "[Clone failed]");
  1295.     close(h);
  1296.     free(buf);
  1297.     return(FALSE);
  1298.     }
  1299.  
  1300. /* dal: configurable variables */
  1301. T_CFG cfg = 
  1302.     {
  1303.         "\177cfg_data>\001\002\004\011__\377@\020\007<..-Dal/JLS",
  1304.         {
  1305.         FALSE,            /* 00: ovrstrk  */
  1306.         0,            /* 01: lmargin  */
  1307.         0,            /* 02: fillcol  */
  1308.         8,            /* 03: tabsize  */
  1309.         FALSE,            /* 04: mousef   */
  1310.         0,            /* 05: mb_right */
  1311.         0,            /* 06: mb_left  */
  1312.         0x0704,            /* 07: m_init.. */
  1313.         0x0A06,            /* 08:   :    */
  1314.         0x0500,            /* 09:   :    */
  1315.         FALSE,            /* 10: autoindent */
  1316.         0            /* 11: cfgchng  */
  1317.         }
  1318.     };
  1319.